﻿/******************************************************************
 *Company: http://www.xiaomutech.com/
 *fileName : qcardarea.cpp --- QCardArea
 *Auth       : yhni (QQ:393320854)
 *Create    : 2022/1/24
 *Description   :
 *Histroy:
 *<Auth>    <Date>        <Ver>        <Content>
 *         2022/1/24
 *******************************************************************/
#include "qcardarea.h"
#include "qaistrategy.h"
#include "qttools.h"

#include <QtMath>
#include <QDebug>
#include <QPainter>
#include <QMouseEvent>
#include <QMatrix>

#define  CARD_SPACE     35

QCardArea::QCardArea(QWidget *parent) : QWidget(parent)
{
    m_areaType = AreaLeft;
    m_pickCard = false;
    m_isPressed = false;
    m_handle = false;

    m_userId = 0;
    m_role = 0;
    m_order = 0;
    m_ready = false;

    initCards();
}

QCardArea::~QCardArea()
{
}

void QCardArea::setAreaType(const AreaType &_areaType)
{
    m_areaType = _areaType;
}

void QCardArea::initCards()
{
#ifdef QT_USE_BIG_IMAGE
    m_pixmapBg = QPixmap(":/images/cards/card_16.png");
#else
    QPixmap pximap(":/images/cards/default.png");
    m_pixmapBg = pximap.copy(2 * CARD_WIDTH, 4 * CARD_HEIGHT, CARD_WIDTH, CARD_HEIGHT);
#endif
    m_cards.clear();
}

void QCardArea::addCard(QCard *_card)
{
    m_cards.insert(_card->type(), _card);
    adjuest();
}

void QCardArea::addCards(CardList _cards)
{
    clear();
    foreach (QCard *card, _cards) {
        m_cards.insert(card->type(), card);
    }
    adjuest();
}

CardList QCardArea::getCards()
{
    return m_cards.values();
}

void QCardArea::remove(QCard *card)
{
    if (m_cards.contains(card->type())) {
        m_cards.remove(card->type());
//        delete card;
//        card = NULL;
    }
}

void QCardArea::remove(CardList _cards)
{
    foreach (QCard *card, _cards) {
        if (NULL != card) {
            remove(card);
        }
    }
    adjuest();
}

void QCardArea::remove(QList<CardType> _cards)
{
    foreach (CardType _card, _cards) {
        if (!m_cards.contains(_card)) continue;
        QCard *card = m_cards.value(_card);
        m_cards.remove(_card);
        delete card;
        card = NULL;
    }

    adjuest();
}

void QCardArea::clear()
{
    foreach (QCard *card, m_cards) {
        m_cards.remove(card->type());
        delete card;
        card = NULL;
    }

    adjuest();
}

QSize QCardArea::cardSize() const
{
    return QSize(CARD_WIDTH, CARD_HEIGHT);
}

void QCardArea::setSort(int _type)
{
    QList<CardType> cardList = m_cards.keys();
    CardList cards = m_cards.values();

    if (_type == 0) {
        std::sort(cardList.begin(), cardList.end(), std::less<CardType>());
    } else {
        std::sort(cardList.begin(), cardList.end(), std::greater<CardType>());
    }

    m_cards.clear();
    foreach(CardType _type, cardList) {
        foreach(QCard *card, cards) {
            if (card->type() == _type) {
                m_cards.insert(_type, card);
                break;
            }
        }
    }

    adjuest();
}

void QCardArea::setPickCard(bool Ok)
{
    if (AreaCenter == m_areaType) {
        m_pickCard = Ok;
        this->update();
    }
}

quint16 QCardArea::getUserId() const
{
    return m_userId;
}

void QCardArea::setUserId(const quint16 &userId)
{
    m_userId = userId;
    this->update();
}

quint8 QCardArea::getRole() const
{
    return m_role;
}

void QCardArea::setRole(const quint8 &role)
{
    m_role = role;
}

bool QCardArea::isReady()
{
    return 1 == m_ready;
}

void QCardArea::setReady(bool ready)
{
    m_ready = ready;
    this->update();
}

quint8 QCardArea::getOrder() const
{
    return m_order;
}

void QCardArea::setOrder(const quint8 &order)
{
    m_order = order;
}

bool QCardArea::isHandle()
{
    return m_handle;
}

void QCardArea::setHandle(bool bOk)
{
    m_handle = bOk;
}

void QCardArea::playCards(CardList _cards, bool self)
{
    if (!m_handle) return;

    CardList pickCards;
    foreach (QCard *card, m_cards) {
        if (card->selected()) {
            pickCards.push_back(card);
        }
    }

    if (!pickCards.isEmpty()) {
        QCardHand hand;
        hand.fromCards(pickCards);

        if (!self && !_cards.isEmpty()) {
            QCardHand other;
            other.fromCards(_cards);

            if (hand.judgeHand() != other.judgeHand() &&
                    hand.judgeHand() != Hand_Bomb &&
                    hand.judgeHand() != Hand_Bomb_Jokers)
            {
                qDebug() << "出牌类型不一致";
                return;
            }

            if (other > hand) {
                qDebug() << "无法大过对手的牌";
                return;
            }
        }

        if (hand.judgeHand() == Hand_Unknown) {
            return;
        }

        foreach (QCard *card, pickCards) {
            remove(card);
        }

        emit playCards(hand.judgeHand(), pickCards);
        adjuest();
    }

    m_handle = false;
}

void QCardArea::thinkPlayCars(CardList _cards, bool isLoard)
{
    if (!isLoard) return;
    QCardHand other;
    other.fromCards(_cards);
    QAiStrategy my(m_cards.values());
    CardList _pickCards = my.playBeatHand(other);
    playCards(_pickCards, true);
}

void QCardArea::adjuest()
{
    int nW = m_cards.size() * CARD_SPACE + CARD_WIDTH;
    int nX = (this->width() - nW) / 2;
    int nY = this->height() - CARD_HEIGHT - 10;
    int i = 0;

    if (AreaLeft == m_areaType || AreaRight == m_areaType) {
        nW = m_cards.size() * 10 + CARD_HEIGHT * 0.6;
        nX = AreaLeft == m_areaType ? (this->width() - CARD_WIDTH * 0.6) : 0;
        nY = (this->height() - nW) / 2;
    } else if (AreaTop == m_areaType) {
        nW = 3 * CARD_WIDTH + 20 * 2;
        nX = (this->width() - nW) / 2;
        nY = (this->height() - CARD_HEIGHT) / 2;
    } else if (AreaCenter == m_areaType) {
        nW = m_cards.size() * CARD_SPACE;
        nX = (this->width() - nW) / 2;
        nY = (this->height() - CARD_HEIGHT) / 2;
    }

    foreach(QCard *card, m_cards) {
        if (AreaBottom == m_areaType || AreaCenter == m_areaType) {
            card->setRect(QRect(nX + i++ * CARD_SPACE, nY, CARD_WIDTH, CARD_HEIGHT));
        } else if (AreaLeft == m_areaType || AreaRight == m_areaType) {
            card->setRect(QRect(nX, nY, CARD_WIDTH * 0.6, CARD_HEIGHT * 0.6));
            nX += (AreaLeft == m_areaType ? -6 : 6);
            nY += 10;
        } else if (AreaTop == m_areaType) {
            card->setRect(QRect(nX + i++ * (CARD_WIDTH + 20), nY, CARD_WIDTH, CARD_HEIGHT));
        }
    }

    this->update();
}

void QCardArea::resizeEvent(QResizeEvent *e)
{
    adjuest();
    QWidget::resizeEvent(e);
}

void QCardArea::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
#if 0
    if (AreaLeft == m_areaType || AreaRight == m_areaType || AreaBottom == m_areaType) {

        painter.save();
        painter.setPen(QColor("#aaaaaa"));
        painter.drawText(QRect(0, 0, this->width(), 30), Qt::AlignCenter, 0 != m_userId ?
                    QString("%1(%2): %3").arg(m_userId).arg(m_order).arg(isReady() ? "已准备" : "等待中") : QString("无人"));
        painter.restore();
    }
#endif

    foreach (QCard *card, m_cards) {
        if (AreaTop == m_areaType) {
            painter.drawPixmap(card->rect(), m_ready ? card->pixmap() : m_pixmapBg);
        } else if (AreaBottom == m_areaType) {
            QRect rect = card->rect();
            if (card->selected()) {
                rect = QRect(rect.left(), rect.top() - 20, rect.width(), rect.height());
            }
            painter.drawPixmap(rect, card->pixmap());
            if (card->pressed()) {
                painter.save();
                painter.setPen(Qt::NoPen);
                painter.setBrush(QColor("#33000000"));
                painter.drawRoundedRect(rect, 5, 5);
                painter.restore();
            }
        } else if (AreaCenter == m_areaType) {
            if (m_pickCard && m_cards.isEmpty()) {
                QRect rect = QRect((this->width() - CARD_WIDTH) / 2,
                                   (this->height() - CARD_HEIGHT) / 2,
                                   CARD_WIDTH, CARD_HEIGHT);
                painter.drawPixmap(rect, m_pixmapBg);
            }
            else painter.drawPixmap(card->rect(), card->pixmap());
        } else {
            QMatrix matrix;
            matrix.rotate(AreaLeft == m_areaType ? -120 : 120);
            QPixmap thisPix = m_pixmapBg.transformed(matrix, Qt::SmoothTransformation);
            painter.drawPixmap(card->rect(), thisPix);
#if 0
            painter.save();
            painter.setPen(QColor("#ffffff"));
            QFont font = painter.font();
            font.setBold(true);
            painter.setFont(font);
            painter.drawText(QRect(this->width() - 30, this->height() / 2 - 15, 30, 30), Qt::AlignCenter, QString::number(m_cards.size()));
            painter.restore();
#endif
        }
    }
}

void QCardArea::mousePressEvent(QMouseEvent *e)
{
    if (AreaBottom != m_areaType) return;
    if (Qt::LeftButton == e->button()) {
        foreach (QCard *card, m_cards) {
            QRect rect = card->rect();
            rect = QRect(rect.left(), rect.top(), card == m_cards.last() ? rect.width() : CARD_SPACE, rect.height());
            if (rect.contains(e->pos())) {
                card->setPressed(true);
                this->update();
                break;
            }
        }

        m_isPressed = true;
        m_startPos = e->pos();
    }

    QWidget::mousePressEvent(e);
}

void QCardArea::mouseMoveEvent(QMouseEvent *e)
{
    if (AreaBottom != m_areaType || !m_isPressed) return;

    foreach (QCard *card, m_cards) {
        QRect rect = card->rect();
        rect = QRect(rect.left(), rect.top(), CARD_SPACE, rect.height());
        if (rect.contains(QPoint(e->pos()))) {
            card->setPressed(true);
        }
    }

    this->update();
    QWidget::mouseMoveEvent(e);
}

void QCardArea::mouseReleaseEvent(QMouseEvent *e)
{
    QWidget::mouseReleaseEvent(e);
    if (AreaBottom != m_areaType || !m_isPressed) return;

    if (Qt::LeftButton == e->button()) {
        foreach (QCard *card, m_cards) {
            if (card->pressed()) {
                card->setPressed(false);
                card->setSelected(!card->selected());
            }
        }

        this->update();
    }
}

////////////////////////////////////////////////////////////////////////////////////

QCard::QCard(CardType _type, const QPixmap &_pix) : m_type(_type), m_pixmap(_pix),
    m_selected(false),m_pressed(false)
{
}

QRect QCard::rect() const
{
    return m_rect;
}

void QCard::setRect(const QRect &rect)
{
    m_rect = rect;
}

bool QCard::selected() const
{
    return m_selected;
}

void QCard::setSelected(bool isSelected)
{
    m_selected = isSelected;
}

QPixmap QCard::pixmap() const
{
    return m_pixmap;
}

void QCard::setPixmap(const QPixmap &pixmap)
{
    m_pixmap = pixmap;
}

CardType QCard::type() const
{
    return m_type;
}

bool QCard::pressed() const
{
    return m_pressed;
}

void QCard::setPressed(bool pressed)
{
    m_pressed = pressed;
}
